package com.kalvan.core.redis;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;
import java.time.Duration;

/****
 * 手动连接redis 生成工具类
 * @author chenliang
 */
@Configuration
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {

    @Resource
    private RedisProperties redisProperties;

    /**
     * jedis配置
     *
     * @return
     */
    public JedisPoolConfig getJedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(redisProperties.getPoolProperties().getMaxIdle());
        config.setMaxWaitMillis(redisProperties.getPoolProperties().getMaxWait());
        config.setMaxTotal(redisProperties.getPoolProperties().getMaxActive());
        return config;
    }

    /**
     * 获取jedispool
     *
     * @return
     */
    @Bean
    public JedisPool getJedisPool() {
        JedisPoolConfig config = getJedisPoolConfig();

        JedisPool jedisPool;
        if (StringUtils.isBlank(redisProperties.getPassword())) {
            jedisPool = new JedisPool(
                    config,
                    redisProperties.getHost(),
                    redisProperties.getPort(),
                    redisProperties.getCommandTimeout());
        } else {
            jedisPool = new JedisPool(
                    config,
                    redisProperties.getHost(),
                    redisProperties.getPort(),
                    redisProperties.getCommandTimeout(),
                    redisProperties.getPassword());
        }

        return jedisPool;
    }

//    /**
//     * 使用方式一
//     *
//     * @return
//     */
//    @Bean(name = "jedisCluster")
//    public JedisCluster getJedisCluster() {
//        if (StringUtils.isBlank(redisProperties.getClusterNodes())) {
//            return null;
//        }
//        log.info("redis加载{}", redisProperties.getClusterNodes());
//        // 处理集群node节点配置
//        String[] serverArray = redisProperties.getClusterNodes().split(",");
//        Set<HostAndPort> nodes = new HashSet<>();
//        for (String ipPort : serverArray) {
//            String[] ipPortPair = ipPort.split(":");
//            nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
//        }
//        // Redis连接池配置
//        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
//        poolConfig.setMaxIdle(redisProperties.getPoolProperties().getMaxIdle());
//        poolConfig.setMinIdle(redisProperties.getPoolProperties().getMinIdle());
//        poolConfig.setMaxWaitMillis(redisProperties.getPoolProperties().getMaxWait());
//        poolConfig.setMaxTotal(redisProperties.getPoolProperties().getMaxActive());
//        if (StringUtils.isBlank(redisProperties.getPassword())) {
//            return new JedisCluster(nodes, redisProperties.getCommandTimeout(), redisProperties.getExpireSeconds(), 1,
//                    poolConfig);
//        } else {
//            return new JedisCluster(nodes, redisProperties.getCommandTimeout(), redisProperties.getExpireSeconds(), 1,
//                    redisProperties.getPassword(), poolConfig);
//        }
//    }
//

    /**
     * 配置 Redis 连接工厂
     */
    @Bean
    public RedisConnectionFactory getJedisConnectionFactory() {
        //配置
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(redisProperties.getPoolProperties().getMaxIdle());
        jedisPoolConfig.setMinIdle(redisProperties.getPoolProperties().getMinIdle());
        jedisPoolConfig.setMaxWaitMillis(redisProperties.getPoolProperties().getMaxWait());
        jedisPoolConfig.setMaxTotal(redisProperties.getPoolProperties().getMaxActive());
        jedisPoolConfig.setTestOnBorrow(true);
        jedisPoolConfig.setTestOnCreate(true);
        jedisPoolConfig.setTestWhileIdle(true);

        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
                .usePooling().poolConfig(jedisPoolConfig).and().readTimeout(Duration.ofMillis(redisProperties.getCommandTimeout())).build();
        // 单点redis
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        // 哨兵redis
        // RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();
        // 集群redis
//        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
//        List<RedisNode> nodeList = new ArrayList<>();
//        String[] cNodes = redisProperties.getClusterNodes().split(",");
//        // 分割出集群节点
//        for (String node : cNodes) {
//            String[] hp = node.split(":");
//            nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1])));
//        }
//        redisClusterConfiguration.setClusterNodes(nodeList);
//        redisConfig.setDatabase(redisDb);
        redisConfig.setHostName(redisProperties.getHost());
        redisConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));
        redisConfig.setPort(redisProperties.getPort());
        return new JedisConnectionFactory(redisConfig, clientConfig);
    }

    /**
     * 使用方式二 spring 内置
     * 设置数据存入redis 的序列化方式 redisTemplate序列化默认使用的jdkSerializeable
     * 存储二进制字节码，导致key会出现乱码，所以自定义序列化类
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //生成 RedisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.afterPropertiesSet();
        redisTemplate.setEnableTransactionSupport(false);

        return redisTemplate;
    }

}
